﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Text;
using System.Net;
using System.IO;
using Quartz;
using Quartz.Impl;
using System.Web.Hosting;
using System.Messaging;

/// <summary>
/// DelayCronService 的摘要说明
/// </summary>
public class DelayCronService : IRegisteredObject
{
    private readonly object _lock = new object();

    private bool _started = false;

	public DelayCronService()
	{
        HostingEnvironment.RegisterObject(this);
	}

    private static DelayCronService _instance = null;

    public static DelayCronService Instance
    {
        get
        {
            if (_instance == null)
                _instance = new DelayCronService();

            return _instance;
        }
    }

    private IScheduler _scheduler = null;

    public IScheduler Scheduler
    {
        get
        {
            if (_scheduler == null)
            {
                ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
                IScheduler scheduler = schedulerFactory.GetScheduler();

                _scheduler = scheduler;
            }
            return _scheduler;
        }
    }

    public void Start()
    {

        lock (_lock)
        {
            if (_started)
                return;

            _started = true;

            Maticsoft.BLL.bll_api_delay bll = new Maticsoft.BLL.bll_api_delay();
            DataTable dt = bll.GetAllList().Tables[0];

            foreach (DataRow row in dt.Rows)
            {
                GMS.Core.Config.DelayUrlInfo urlInfo = new GMS.Core.Config.DelayUrlInfo();

                urlInfo.Id = row["id"].ToString();
                urlInfo.Name = row["apiname"] as string;
                urlInfo.Ready = bool.Parse(row["isusing"].ToString());

                if (!urlInfo.Ready)
                    continue;

                urlInfo.Schedule = row["apimemo"] as string;
                urlInfo.Url = row["apiurl"] as string;
                urlInfo.ContentType = row["contenttype"] as string;
                urlInfo.Content = row["content"] as string;
                urlInfo.HttpMethod = row["httpmethod"] as string;

                urlInfo.AppCode = row["appcode"] as string;
                urlInfo.AppQueue = row["appqueue"] as string;


                IJobDetail jobDetail = JobBuilder.Create<HttpJob>()
               .WithIdentity("Delay_Job" + urlInfo.Id)
               .Build();

                jobDetail.JobDataMap.Add("DelayUrlInfo", urlInfo);

                ITrigger trigger = TriggerBuilder.Create()
                    .ForJob(jobDetail)
                    .WithCronSchedule(urlInfo.Schedule)
                    .WithIdentity("Delay_Trigger" + urlInfo.Id)
                    .StartNow()
                    .Build();


                this.Scheduler.ScheduleJob(jobDetail, trigger);
                this.Scheduler.Start();
            }
        }
    }

    public void Stop(bool immediate)
    {
        lock (_lock)
        {
            _started = false;

            this.Scheduler.Clear();
        }
        _instance = null;
        HostingEnvironment.UnregisterObject(this);
    }


    /// <summary>
    /// 重新启动
    /// </summary>
    public void Restart()
    {
        this.Stop(true);

        this.Start();
    }
    
    public class HttpJob : IJob, IRegisteredObject
    {   
        static IMessageFormatter formatter = new System.Messaging.BinaryMessageFormatter();

        public HttpJob()
        {
            HostingEnvironment.RegisterObject(this);
        }

        public static int timeoutSecond = int.Parse(System.Configuration.ConfigurationManager.AppSettings["timeoutSecond"]);

        public void Execute(IJobExecutionContext context)
        {   
            var ui = context.JobDetail.JobDataMap.Get("DelayUrlInfo") as GMS.Core.Config.DelayUrlInfo;

            MessageQueueTransaction transaction = new MessageQueueTransaction();

            try
            {   
                MessageQueue queue = new MessageQueue(ui.AppQueue);
                transaction.Begin();
                Message[] messages = queue.GetAllMessages();

                if (messages == null || messages.Length == 0)
                    return;

                Message message = queue.Receive(transaction);
                message.Formatter = formatter;

                string reckey = message.Label;
                string data = message.Body.ToString();

                
                if (ui.HttpMethod.ToLower().Equals("get"))
                {
                    var result = HttpGet(ui.Url, data, ui.ContentType);
                    
                    transaction.Commit();
                    GMS.Core.Log.Log4NetHelper.LogInput(GMS.Core.Log.Log4NetHelper.LogType.Delayed, "调用API正常", ui.Name, ui.Url, ui.HttpMethod, result);
                }
                else if (ui.HttpMethod.ToLower().Equals("post"))
                {
                    var result = HttpPost(ui.Url, data, ui.ContentType);
                    transaction.Commit();

                    GMS.Core.Log.Log4NetHelper.LogInput(GMS.Core.Log.Log4NetHelper.LogType.Delayed, "调用API正常", ui.Name, ui.Url, ui.HttpMethod, result);
                }
            }
            catch (Exception ex)
            {   
                transaction.Abort();
                GMS.Core.Log.Log4NetHelper.LogErrorInput(GMS.Core.Log.Log4NetHelper.LogType.Delayed, ex, "调用API异常", ui.Name, ui.Url, ui.HttpMethod);
            }
        }

        public static string HttpGet(string Url, string postDataStr, string contentType)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url + (postDataStr == "" ? "" : "?") + postDataStr);
            request.Method = "GET";
            request.ContentType = contentType;
            request.Timeout = 1000 * timeoutSecond;

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream myResponseStream = response.GetResponseStream();
            StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.UTF8);
            string retString = myStreamReader.ReadToEnd();
            myStreamReader.Close();
            myResponseStream.Close();

            return retString;
        }


        public static string HttpPost(string Url, string postData, string contentType)
        {
            HttpWebRequest webrequest = (HttpWebRequest)HttpWebRequest.Create(Url);
            webrequest.Method = "POST";
            webrequest.Timeout = 1000 * timeoutSecond;

            byte[] postdatabyte = Encoding.UTF8.GetBytes(postData);
            webrequest.ContentType = contentType;

            webrequest.ContentLength = postdatabyte.Length;
            Stream stream;
            stream = webrequest.GetRequestStream();
            stream.Write(postdatabyte, 0, postdatabyte.Length);
            stream.Close();

            using (var httpWebResponse = webrequest.GetResponse())
            using (StreamReader responseStream = new StreamReader(httpWebResponse.GetResponseStream()))
            {
                String ret = responseStream.ReadToEnd();

                return ret;
            }
        }

        public void Stop(bool immediate)
        {
            HostingEnvironment.UnregisterObject(this);
        }

    }
    


}